#include "ObjectManager.h"
#include "GameObject.h"
#include <iostream>
ObjectManager::ObjectManager(void)
	: 
	m_firstObject(0),
	m_lastObject(0),
	m_count(0)
{

}
ObjectManager::~ObjectManager(void)
{
	RemoveAll();
}
void* ObjectManager::Add(GameObject& obj)
{
	void* address = m_allocator.Allocate(obj.GetObjSize() + sizeof(ObjectNode));
	ObjectNode* node = (ObjectNode*)address;
	node->obj = (GameObject*)(node + 1);
	node->next = 0;

	obj.Copy(node->obj);

	if (!m_firstObject)
	{
		m_firstObject = node;
		node->previous = 0;
	}
	if (m_lastObject)
	{
		m_lastObject->next = node;
		node->previous = m_lastObject;
	}
	m_lastObject = node;
	m_count++;
	return ((ObjectNode*)address)+1;
}
bool ObjectManager::Remove(long long objID)
{
	ObjectNode* node = m_firstObject;
	while (node)
	{
		if (node->obj->GetID() == objID)
		{
			return DeleteObject(node);
		}
		node = node->next;
	}
	return false;
}
bool ObjectManager::RemoveAll(void)
{
	ObjectNode* node = m_firstObject;
	while (node)
	{
		DeleteObject(node);
		node = node->next;
	}
	m_firstObject = 0;
	m_lastObject = 0;
	return true;
}
bool ObjectManager::DeleteObject(ObjectNode* node)
{
	if (m_firstObject == node && m_lastObject == node)
	{
		m_firstObject = 0;
		m_lastObject = 0;
	}
	else if (m_firstObject == node)
	{
		m_firstObject = node->next;
		node->next->previous = 0;
	}
	else if (m_lastObject == node)
	{
		m_lastObject = node->previous;
		node->previous->next = 0;
	}
	else
	{
		node->previous->next = node->next;
		node->next->previous = node->previous;
	}

	node->obj->~GameObject();
	m_allocator.Free(node);
	m_count--;
	return true;
}
void ObjectManager::PerformOperationOnAllObjects(objectFunc func)
{
	ObjectNode* node = m_firstObject;
	while (node)
	{
		func(node->obj);
		node = node->next;
	}
}
GameObject* ObjectManager::FindObject(long long objectID) const
{
	ObjectNode* node = m_firstObject;
	while (node)
	{
		if (objectID == node->obj->GetID())
			return node->obj;

		node = node->next;
	}
	return 0;
}
void ObjectManager::PrintObjects(void) const
{
	system("cls");
	ObjectNode* node = GetFirstObject();
	while (node)
	{
		OBJECT_TYPE type = node->obj->GetObjType();
		Position& pos = node->obj->GetPosition();
		char const* typeName = 0;
		switch (type)
		{
			case OBJECT_TYPE::BASE:
				typeName = "BASE";
				break;
			case OBJECT_TYPE::BEAM:
				typeName = "BEAM";
				break;
			case OBJECT_TYPE::ENEMY:
				typeName = "ENEMY";
				break;
			case OBJECT_TYPE::FOLLOWER:
				typeName = "FOLLOWER";
				break;
			case OBJECT_TYPE::PLAYER:
				typeName = "PLAYER";
				break;
			case OBJECT_TYPE::PROJECTILE:
				typeName = "PROJECTILE";
				break;
			default:
				typeName = "UNKNOWN";
		}
		std::cout << "OBJ_TYPE:  " << typeName << "  size:  " << node->obj->GetObjSize() << std::endl
				  << "Position:  x:" << pos.x << std::endl
				  << "           y:" << pos.y << std::endl;
		node = node->next;
	}
}
ObjectNode* ObjectManager::GetFirstObject(void) const
{
	return m_firstObject;
}
ObjectNode* ObjectManager::GetLastObject(void) const
{
	return m_lastObject;
}
int ObjectManager::GetCount(void) const
{
	return m_count;
}